Creating Elegant Tables in R with Flextable

Introduction

The flextable package in R is used to create highly customizable tables for reporting in Word, PowerPoint, HTML, and PDF. It allows the users to style tables with control over fonts, alignment, borders, colors, and formatting. Flextable integrates well with Quarto and R Markdown, making it ideal for producing polished, publication-ready tables.

Import the data

data <- read.csv("C:/Users/Admin/OneDrive/Desktop/Office/MyStudyApp/merge.csv",header = TRUE)

About the data set

head(data)
  Patient_ID  Day VAS PGA Age Gender Treatment Center ITT  PP
1    PID/001 DAY1  72   2  24 Female   PLACEBO     C1 YES YES
2    PID/001 DAY5  56   2  24 Female   PLACEBO     C1 YES YES
3    PID/001 DAY6  67   2  24 Female   PLACEBO     C1 YES YES
4    PID/001 DAY4  56   2  24 Female   PLACEBO     C1 YES YES
5    PID/001 DAY2  70   2  24 Female   PLACEBO     C1 YES YES
6    PID/001 DAY7  62   2  24 Female   PLACEBO     C1 YES YES

Create a summary table to analyse VAS and PGA for each Day grouped by treatment

library(flextable)
library(dplyr)
library(tidyr)

# Step 1: Summarize VAS and PGA as "Mean (SD)"
#Prepare the Summary Table 
summary_wide <- data %>%
#Groups the data by Day and Treatment.
  group_by(Day, Treatment) %>%
#Calculates the mean and standard deviation of VAS and PGA, formatting them as "Mean (SD)".
  summarise(
    VAS = sprintf("%.2f (%.2f)", mean(VAS, na.rm = TRUE), sd(VAS, na.rm = TRUE)),
    PGA = sprintf("%.2f (%.2f)", mean(PGA, na.rm = TRUE), sd(PGA, na.rm = TRUE)),
    .groups = "drop"
  ) %>%
#Uses pivot_wider() to reshape the data so each treatment group has its own column.
  pivot_wider(
    names_from = Treatment,
    values_from = c(VAS, PGA),
    names_glue = "{.value}_{Treatment}"
  ) %>%
#Arranges rows in ascending order by Day.
  arrange(Day)

# Extract column names for VAS and PGA
vas_cols <- grep("^VAS_", names(summary_wide), value = TRUE)
pga_cols <- grep("^PGA_", names(summary_wide), value = TRUE)

# Step 2: Flextable with updated coloring
ft <- flextable(summary_wide) %>%
#Renames column headers
  set_header_labels(
    VAS_PLACEBO = "VAS_PLACEBO",
    VAS_REF = "VAS_REF",
    VAS_TEST = "VAS_TEST",
    PGA_PLACEBO = "PGA_PLACEBO",
    PGA_REF = "PGA_REF",
    PGA_TEST = "PGA_TEST"
  ) %>%
#autofit() adjusts column widths to fit content.
  autofit() %>%
#theme_booktabs() applies a clean table theme.
  theme_booktabs() %>%
#bold(part = "header") bolds the column headers.
  bold(part = "header") %>%
#align() centers all text in the table.
  align(align = "center", part = "all") %>%
  bg(i = ~ seq_len(nrow(summary_wide)) %% 2 == 0, bg = "#f2f2f2") %>%   # Zebra rows
  bg(j = vas_cols, bg = "#cce5ff", part = "body") %>%   # Light Blue for VAS
  bg(j = pga_cols, bg = "#fff5cc", part = "body")       # Light Yellow for PGA

ft

Day

VAS_PLACEBO

VAS_REF

VAS_TEST

PGA_PLACEBO

PGA_REF

PGA_TEST

DAY1

64.56 (14.56)

63.41 (16.75)

62.74 (17.61)

0.94 (0.61)

3.89 (0.33)

3.89 (0.31)

DAY2

57.36 (14.18)

46.74 (19.88)

45.76 (20.66)

0.94 (0.61)

3.89 (0.33)

3.89 (0.31)

DAY3

49.02 (16.32)

29.59 (21.48)

29.11 (21.70)

0.94 (0.61)

3.89 (0.33)

3.89 (0.31)

DAY4

41.11 (15.08)

21.82 (17.68)

21.17 (17.79)

0.94 (0.61)

3.89 (0.33)

3.89 (0.31)

DAY5

35.22 (15.21)

17.57 (15.76)

17.06 (15.82)

0.94 (0.61)

3.89 (0.33)

3.89 (0.31)

DAY6

31.36 (17.27)

13.34 (14.63)

12.96 (14.36)

0.94 (0.61)

3.89 (0.33)

3.89 (0.31)

DAY7

28.00 (18.21)

11.11 (13.99)

10.73 (13.71)

0.94 (0.61)

3.89 (0.33)

3.89 (0.31)

Common Functions and Purpose

  • flextable() Converts a data frame or tibble into a flextable object, which is the core of the table-building process.

  • set_header_labels() Sets the column header labels to more descriptive names (e.g., changing VAS_PLACEBO to VAS (Placebo)).

  • autofit() Adjusts column widths automatically so that the content fits neatly.

  • theme_booktabs() Applies a booktabs-style theme to the table, which gives it a clean and professional appearance (with minimal lines).

  • align() Aligns the contents of specified columns. In your case, it’s aligning columns 2 through 5 to the center. The part = “all” argument ensures the alignment applies to all parts of the table (header, body, and footer).

Conclusion:

Unique Word & PowerPoint Support: Seamlessly integrates with officer to produce styled tables in Word/PPT—unmatched by other packages.

High Customization: Offers detailed control over fonts, colors, borders, alignment, and cell merging.

Professional Output: Ideal for publication-ready reports with themes like theme_booktabs.

Multi-format Export: Supports HTML, PDF, Word, and PowerPoint outputs.

Advanced Layouts: Easily build complex tables with custom headers, footnotes, and conditional formatting.